import { type Config as SvgrOptions, transform } from '@svgr/core';
import camelcase from 'camelcase';
import fs from 'fs';
import { glob } from 'glob';
import path from 'path';

export interface TransformSvgToComponentArgs {
  entryDir: string;
  outputDir: string;
  svgProps?: Record<string, string>;
  svgrOptions?: SvgrOptions;
  prefix?: string;
  suffix?: string;
}

/**
 * 把一个文件夹下的所有 svg 文件转换为 react 组件
 * @param args 转换参数
 * @param args.entryDir 输入文件夹
 * @param args.outputDir 输出文件夹
 * @param args.svgProps svg 属性
 * @param args.svgrOptions svgr 配置
 * @param args.prefix 前缀
 * @param args.suffix 后缀
 */
export async function transformSvgToComponent(
  args: TransformSvgToComponentArgs,
) {
  const {
    entryDir,
    outputDir,
    svgProps = {},
    svgrOptions = {},
    prefix = '',
    suffix = '',
  } = args;

  fs.rmSync(outputDir, { recursive: true, force: true });
  fs.mkdirSync(outputDir, { recursive: true });

  const files = await glob(path.resolve(entryDir, '**/*.svg'));

  const list = files.map((value) => generateComponent(value));

  const arr = await Promise.all(list);

  const indexFileContent = arr
    .map(
      (a) =>
        `export { default as ${a.componentName} } from './${a.componentName}';`,
    )
    .join('\n');

  fs.writeFileSync(
    path.resolve(outputDir, 'index.ts'),
    `// 通过脚本生成\n${indexFileContent}`,
    'utf-8',
  );

  async function generateComponent(filePath: string) {
    const svgCode = fs.readFileSync(filePath, 'utf-8');
    const svgFileName = path.basename(filePath, '.svg');

    const componentCode = await transform(svgCode, {
      svgProps: {
        'aria-label': `${svgFileName}.svg`,
        ...svgProps,
      },
      plugins: [
        '@svgr/plugin-svgo',
        '@svgr/plugin-jsx',
        '@svgr/plugin-prettier',
      ],
      ...svgrOptions,
    });

    const componentName = camelcase(`${prefix}-${svgFileName}-${suffix}`, {
      pascalCase: true,
    });
    const componentFileName = `${componentName}.tsx`;
    const componentFilePath = path.resolve(outputDir, componentFileName);
    fs.writeFileSync(componentFilePath, componentCode, 'utf-8');

    return {
      componentName,
      componentFileName,
      componentFilePath,
    };
  }
}
